﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;

namespace NGCDS
{
    class FTPProtocol : Protocol
    {
        public FTPProtocol(Session session, LogHandeler log)
        {
            this.session = session;
            this.log = log;
        }

        public override string getAuthenticationID(bool isAdminUser = false)
        {
            return "GOOD";
        }

        public override bool DownloadFile(RemoteFileInfo r, string localFile)
        {
            bool isSuccess = false;
            FtpWebRequest request;
            try
            {
                FileStream fs = new FileStream(localFile, FileMode.Create, FileAccess.Write);
                using (BinaryWriter writer = new BinaryWriter(new BufferedStream(fs)))
                {
                    string uriString = string.Format("ftp://{0}:{1}/{2}/{3}",
                        session.getServerIP(), session.getPort(), session.getRemotePath(), r.FileName);
                    request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uriString));
                    request.Credentials = new NetworkCredential(session.getUserId(), session.getPassword());
                    request.Method = WebRequestMethods.Ftp.DownloadFile;
                    request.UseBinary = true;
                    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                    BinaryReader reader = new BinaryReader(new BufferedStream(response.GetResponseStream()));
                    long totalReadedBytes = 0;
                    long length = response.ContentLength;
                    int len;
                    byte[] buffer = new byte[BUFFER_SIZE];
                    while ((len = reader.Read(buffer, 0, BUFFER_SIZE)) > 0)
                    {
                        totalReadedBytes += len;
                        writer.Write(buffer, 0, len);
                    }
                    response.Close();
                    reader.Close();

                    if (totalReadedBytes == length)
                    {
                        isSuccess = true;
                    }
                }
                fs.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
            return isSuccess;
        }

        public override SortedDictionary<string, RemoteFileInfo> GetFileList()
        {
            SortedDictionary<string, RemoteFileInfo> infos = new SortedDictionary<string, RemoteFileInfo>();
            FtpWebRequest reqFTP;
            try
            {
                string uriString = string.Format("ftp://{0}:{1}/{2}/{3}",
                    session.getServerIP(), session.getPort(), session.getRemotePath(), session.getFileName());
                Console.WriteLine(uriString);
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uriString));
                reqFTP.UseBinary = true;
                reqFTP.Credentials = new NetworkCredential(session.getUserId(), session.getPassword());
                reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
                WebResponse response = reqFTP.GetResponse();
                StreamReader reader = new StreamReader(response.GetResponseStream());
                string fileName = null;
                while ((fileName = reader.ReadLine()) != null)
                {
                    string uri = string.Format("ftp://{0}:{1}/{2}/{3}",
                        session.getServerIP(), session.getPort(), session.getRemotePath(), fileName);
                    RemoteFileInfo info = new RemoteFileInfo(fileName, GetDateTime(uri), GetFileSize(uri));
                    infos.Add(info.FileName, info);
                }
                reader.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return infos;
        }

        private long GetFileSize(string uriString)
        {
            long result = 0;
            FtpWebRequest request;
            try
            {
                request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uriString));
                request.UseBinary = true;
                request.Credentials = new NetworkCredential(session.getUserId(), session.getPassword());
                request.Method = WebRequestMethods.Ftp.GetFileSize;
                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                result = response.ContentLength;
                response.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                result = 0;
            }
            return result;
        }

        private DateTime GetDateTime(string uriString)
        {
            DateTime result;
            FtpWebRequest request;
            try
            {
                request = (FtpWebRequest)FtpWebRequest.Create(new Uri(uriString));
                request.UseBinary = true;
                request.Credentials = new NetworkCredential(session.getUserId(), session.getPassword());
                request.Method = WebRequestMethods.Ftp.GetDateTimestamp;
                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                result = response.LastModified;
                response.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                result = DateTime.Now;
            }
            return result;
        }
    }
}
